const logger = require('../config/logger');
const db = require('../config/database');

/**
 * WebSocket连接管理
 */
class SocketManager {
  constructor(io) {
    this.io = io;
    this.clients = new Map(); // 存储客户端连接: userId -> { socketId, lastHeartbeat }
    this.init();
    this.startHeartbeatCheck();
  }

  init() {
    this.io.on('connection', (socket) => {
      logger.info(`客户端连接: ${socket.id}`);

      // 用户认证
      socket.on('authenticate', async (data) => {
        try {
          const { userId, username, clientId } = data;

          // 🔥 如果提供了clientId，先检查设备冲突并强制旧设备下线
          if (clientId) {
            const [users] = await db.query(
              'SELECT client_id, is_online FROM users WHERE id = ?',
              [userId]
            );

            if (users.length > 0) {
              const user = users[0];
              
              // 检查是否已在其他客户端登录
              if (user.client_id && user.client_id !== clientId && user.is_online === 1) {
                logger.warn(`用户 ${username} 已在客户端 ${user.client_id} 登录，将强制旧客户端下线`);
                
                // 强制旧客户端下线
                this.forceLogoutByClientId(user.client_id, '该账号已在其他设备登录');
              }
            }
          }

          // 🔥 保存客户端连接和心跳时间
          this.clients.set(userId, {
            socketId: socket.id,
            lastHeartbeat: Date.now(),
            clientId: clientId || null
          });
          socket.userId = userId;
          socket.username = username;
          socket.clientId = clientId;

          // 🔥 更新用户在线状态和客户端ID
          if (clientId) {
            await db.query(
              'UPDATE users SET is_online = 1, client_id = ?, last_online_at = NOW() WHERE id = ?',
              [clientId, userId]
            );
            logger.info(`用户 ${username} (ID: ${userId}) 从客户端 ${clientId} 已连接`);
          } else {
            await db.query(
              'UPDATE users SET is_online = 1, last_online_at = NOW() WHERE id = ?',
              [userId]
            );
            logger.info(`用户 ${username} (ID: ${userId}) 已连接`);
          }

          socket.emit('authenticated', { success: true });

          // 广播用户上线
          this.io.emit('user-online', { userId, username });

        } catch (error) {
          logger.error('用户认证失败:', error);
          socket.emit('authenticated', { success: false, message: '认证失败' });
        }
      });

      // 🔥 心跳检测
      socket.on('heartbeat', () => {
        if (socket.userId) {
          const client = this.clients.get(socket.userId);
          if (client) {
            client.lastHeartbeat = Date.now();
            socket.emit('heartbeat-ack');
            logger.debug(`收到用户 ${socket.userId} 的心跳，已更新时间`);
          } else {
            logger.warn(`收到心跳但未找到用户 ${socket.userId} 的客户端记录`);
          }
        } else {
          logger.warn('收到未认证客户端的心跳');
        }
      });

      // 文件传输进度更新
      socket.on('transfer-progress', async (data) => {
        try {
          const { taskId, transferred, speed } = data;

          // 更新数据库
          await db.query(
            'UPDATE transfer_tasks SET transferred_size = ?, speed = ?, updated_at = NOW() WHERE id = ?',
            [transferred, speed, taskId]
          );

          // 广播给管理员
          this.io.emit('task-progress', {
            taskId,
            userId: socket.userId,
            transferred,
            speed
          });
        } catch (error) {
          logger.error('更新传输进度失败:', error);
        }
      });

      // 传输状态变化
      socket.on('transfer-status', async (data) => {
        try {
          const { taskId, status, errorMessage } = data;

          await db.query(
            'UPDATE transfer_tasks SET status = ?, error_message = ?, updated_at = NOW() WHERE id = ?',
            [status, errorMessage || null, taskId]
          );

          this.io.emit('task-status-changed', {
            taskId,
            userId: socket.userId,
            status,
            errorMessage
          });

          logger.info(`任务 ${taskId} 状态更新为: ${status}`);
        } catch (error) {
          logger.error('更新传输状态失败:', error);
        }
      });

      // 客户端日志上传
      socket.on('client-log', async (data) => {
        try {
          const { level, message, stackTrace, clientTime } = data;

          await db.query(
            'INSERT INTO client_logs (user_id, level, message, stack_trace, client_time) VALUES (?, ?, ?, ?, ?)',
            [socket.userId, level, message, stackTrace, clientTime]
          );
        } catch (error) {
          logger.error('保存客户端日志失败:', error);
        }
      });

      // 断开连接
      socket.on('disconnect', async () => {
        try {
          if (socket.userId) {
            // 移除客户端连接
            this.clients.delete(socket.userId);

            // 更新用户离线状态
            await db.query(
              'UPDATE users SET is_online = 0, last_online_at = NOW() WHERE id = ?',
              [socket.userId]
            );

            // 广播用户下线
            this.io.emit('user-offline', {
              userId: socket.userId,
              username: socket.username
            });

            logger.info(`用户 ${socket.username} 已断开连接`);
          }
        } catch (error) {
          logger.error('处理断开连接失败:', error);
        }
      });
    });
  }

  /**
   * 🔥 启动心跳检测
   */
  startHeartbeatCheck() {
    // 每30秒检查一次心跳
    setInterval(async () => {
      const now = Date.now();
      const timeout = 60000; // 60秒超时
      const usersToDisconnect = [];

      for (const [userId, client] of this.clients.entries()) {
        if (now - client.lastHeartbeat > timeout) {
          usersToDisconnect.push(userId);
        }
      }

      // 处理超时的连接
      for (const userId of usersToDisconnect) {
        try {
          logger.warn(`用户 ${userId} 心跳超时，标记为离线`);
          
          // 移除客户端连接
          this.clients.delete(userId);

          // 更新数据库状态
          await db.query(
            'UPDATE users SET is_online = 0, last_online_at = NOW() WHERE id = ?',
            [userId]
          );

          // 广播用户下线
          this.io.emit('user-offline', { userId });
        } catch (error) {
          logger.error(`处理用户 ${userId} 超时失败:`, error);
        }
      }
    }, 30000);
  }

  /**
   * 向指定用户发送通知
   */
  sendNotification(userId, notification) {
    const client = this.clients.get(userId);
    if (client) {
      this.io.to(client.socketId).emit('notification', notification);
    }
  }

  /**
   * 广播通知给所有在线用户
   */
  broadcastNotification(notification) {
    this.io.emit('notification', notification);
  }

  /**
   * 根据目标类型发送通知
   */
  async sendNotificationToTargets(notification) {
    try {
      const { targetType, targetIds } = notification;

      if (targetType === 'all') {
        // 发送给所有在线用户（按用户维度发送，每个用户只发送一次）
        let sentCount = 0;
        
        for (const [userId, client] of this.clients.entries()) {
          this.io.to(client.socketId).emit('notification', notification);
          sentCount++;
        }
        
        logger.info(`📢 广播通知给所有在线用户 (${sentCount} 个用户): ${notification.title}`);
        
      } else if (targetType === 'user') {
        // 发送给特定用户（每个用户只发送一次，不管有几个客户端）
        if (targetIds && Array.isArray(targetIds)) {
          let sentCount = 0;
          
          for (const userId of targetIds) {
            const client = this.clients.get(parseInt(userId));
            if (client) {
              this.io.to(client.socketId).emit('notification', notification);
              sentCount++;
              logger.info(`📧 发送通知给用户 ${userId}: ${notification.title}`);
            } else {
              logger.debug(`⚠️  用户 ${userId} 不在线，跳过推送`);
            }
          }
          
          logger.info(`✅ 通知已发送给 ${sentCount}/${targetIds.length} 个目标用户`);
        }
        
      } else if (targetType === 'client') {
        // 发送给特定客户端（按客户端ID匹配）
        if (targetIds && Array.isArray(targetIds)) {
          let sentCount = 0;
          
          for (const clientId of targetIds) {
            // 查找该客户端对应的socket连接
            let found = false;
            
            for (const [userId, client] of this.clients.entries()) {
              if (client.clientId === clientId) {
                this.io.to(client.socketId).emit('notification', notification);
                sentCount++;
                found = true;
                logger.info(`📱 发送通知给客户端 ${clientId} (用户ID: ${userId}): ${notification.title}`);
                break; // 找到后跳出，避免重复发送
              }
            }
            
            if (!found) {
              logger.debug(`⚠️  客户端 ${clientId} 不在线，跳过推送`);
            }
          }
          
          logger.info(`✅ 通知已发送给 ${sentCount}/${targetIds.length} 个目标客户端`);
        }
      }
    } catch (error) {
      logger.error('发送通知失败:', error);
    }
  }

  /**
   * 向指定用户发送任务控制指令
   */
  sendTaskControl(userId, command) {
    const client = this.clients.get(userId);
    if (client) {
      this.io.to(client.socketId).emit('task-control', command);
    }
  }

  /**
   * 获取在线用户列表
   */
  getOnlineUsers() {
    return Array.from(this.clients.keys());
  }

  /**
   * 获取在线客户端列表（包含详细信息）
   */
  getOnlineClients() {
    const clients = [];
    for (const [userId, client] of this.clients.entries()) {
      clients.push({
        userId,
        socketId: client.socketId,
        clientId: client.clientId,
        lastHeartbeat: client.lastHeartbeat
      });
    }
    return clients;
  }

  /**
   * 请求客户端目录列表
   * @param {string} clientId - 客户端ID
   * @param {string} path - 请求的目录路径
   * @returns {Promise} 返回目录列表数据
   */
  async requestClientDirectory(clientId, path = '/') {
    return new Promise((resolve, reject) => {
      try {
        // 查找该客户端对应的socket连接
        let targetSocket = null;
        
        for (const [userId, client] of this.clients.entries()) {
          if (client.clientId === clientId) {
            targetSocket = this.io.sockets.sockets.get(client.socketId);
            break;
          }
        }
        
        if (!targetSocket) {
          return reject(new Error('客户端不在线'));
        }

        // 设置超时
        const timeout = setTimeout(() => {
          reject(new Error('请求超时'));
        }, 30000); // 30秒超时

        // 发送请求并等待响应
        targetSocket.emit('request-directory', { path }, (response) => {
          clearTimeout(timeout);
          if (response && response.success) {
            resolve(response.data);
          } else {
            reject(new Error(response?.message || '获取目录失败'));
          }
        });
      } catch (error) {
        reject(error);
      }
    });
  }

  /**
   * 下发传输任务到客户端
   * @param {string} clientId - 客户端ID
   * @param {Object} task - 传输任务配置
   * @returns {Promise} 返回任务ID
   */
  async dispatchTransferTask(clientId, task) {
    return new Promise((resolve, reject) => {
      try {
        // 查找该客户端对应的socket连接
        let targetSocket = null;
        let targetUserId = null;
        
        for (const [userId, client] of this.clients.entries()) {
          if (client.clientId === clientId) {
            targetSocket = this.io.sockets.sockets.get(client.socketId);
            targetUserId = userId;
            break;
          }
        }
        
        if (!targetSocket) {
          return reject(new Error('客户端不在线或未建立WebSocket连接'));
        }

        logger.info(`📤 下发传输任务到客户端 ${clientId}:`, task);

        // 设置超时
        const timeout = setTimeout(() => {
          reject(new Error('客户端响应超时（30秒）'));
        }, 30000); // 30秒超时

        // 发送传输任务并等待响应
        targetSocket.emit('dispatch-transfer-task', task, (response) => {
          clearTimeout(timeout);
          
          if (response && response.success) {
            logger.info(`✅ 客户端 ${clientId} 已接受任务: ${response.taskId}`);
            resolve(response.taskId);
          } else {
            const errorMsg = response?.message || '客户端拒绝任务';
            logger.error(`❌ 客户端 ${clientId} 拒绝任务: ${errorMsg}`);
            reject(new Error(errorMsg));
          }
        });
      } catch (error) {
        logger.error('下发传输任务失败:', error);
        reject(error);
      }
    });
  }

  /**
   * 🔥 根据客户端ID强制用户下线
   */
  forceLogout(clientId, reason = '该账号已在其他设备登录') {
    this.forceLogoutByClientId(clientId, reason);
  }

  /**
   * 🔥 根据客户端ID强制用户下线（内部方法）
   */
  forceLogoutByClientId(clientId, reason) {
    try {
      // 查找具有该clientId的客户端
      for (const [userId, client] of this.clients.entries()) {
        if (client.clientId === clientId) {
          logger.info(`强制客户端 ${clientId} (用户ID: ${userId}) 下线，原因: ${reason}`);
          
          // 发送强制登出事件
          this.io.to(client.socketId).emit('force-logout', {
            reason: reason,
            timestamp: Date.now()
          });
          
          // 断开连接
          const socket = this.io.sockets.sockets.get(client.socketId);
          if (socket) {
            socket.disconnect(true);
          }
          
          // 从内存中移除
          this.clients.delete(userId);
          
          // 更新数据库状态
          db.query(
            'UPDATE users SET is_online = 0 WHERE id = ?',
            [userId]
          ).catch(err => {
            logger.error('更新用户离线状态失败:', err);
          });
          
          return true;
        }
      }
      
      logger.warn(`未找到客户端ID为 ${clientId} 的活跃连接`);
      return false;
    } catch (error) {
      logger.error('强制下线客户端失败:', error);
      return false;
    }
  }
}

module.exports = SocketManager;
